package com.yuandian.management.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.HashUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuandian.api.business_monitor.entity.BusinessResource;
import com.yuandian.api.management.entity.*;
import com.yuandian.api.management.enums.GraphType;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.bpm.common.security.util.SecurityUtils;
import com.yuandian.management.mapper.ConfResourceMapper;
import com.yuandian.management.service.*;
import com.yuandian.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务资源表-Service实现
 * @author zfsn
 * @date 2023-3-17
 */
@Service
public class ConfResourceServiceImpl extends ServiceImpl<ConfResourceMapper, ConfResource>
		implements ConfResourceService {

	@Autowired
	ConfResourceMapper confResourceMapper;

	@Autowired
	private ConfExclusiveIndicatorService indicatorService;

	@Autowired
	private ConfKeywordService confKeywordService;

	@Autowired
	private ConfDecryptService confDecryptService;

	@Autowired
	private ConfNodePropertyService confNodePropertyService;

	@Lazy
	@Autowired
	public ConfStepService confStepService;

	/**
	 * 分页查询
	 *
	 * @param confResource 筛选条件
	 * @return 通用返回对象
	 */
	@Override
	public Page<ConfResource> listPage(ConfResource confResource) {
		return confResourceMapper.listPage(new Page<>(confResource.getPageNum(), confResource.getPageSize()), confResource);
	}

	/**
	 * 删除资源数据，同时也会删除 改资源下所有 关键字、专属指标、加解密方式
	 *
	 * @param ids 实例对象
	 * @return 通用返回对象
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean removeBatchByIds(List<Integer> ids) {
		List<String> resourceCodes = super.listByIds(ids).stream().map(ConfResource::getResourceCode).collect(Collectors.toList());
		if (!resourceCodes.isEmpty()) {
			//删除该资源所属下的专属指标
			UpdateWrapper<ConfExclusiveIndicator> indicatorUpdateWrapper = new UpdateWrapper<>();
			indicatorUpdateWrapper.in(RESOURCE_CODE, resourceCodes);
			indicatorService.remove(indicatorUpdateWrapper);

			//删除该资源所属下的关键字
			UpdateWrapper<ConfKeyword> keywordUpdateWrapper = new UpdateWrapper<>();
			keywordUpdateWrapper.in(RESOURCE_CODE, resourceCodes);
			confKeywordService.remove(keywordUpdateWrapper);

			//删除该资源所属下的加解密方式
			UpdateWrapper<ConfDecrypt> decryptUpdateWrapper = new UpdateWrapper<>();
			decryptUpdateWrapper.in(RESOURCE_CODE, resourceCodes);
			confDecryptService.remove(decryptUpdateWrapper);
		}
		return super.removeBatchByIds(ids);
	}

	/**
	 * 确认业务服务资源
	 *
	 * @param resourceCodes 主键
	 * @param isConfirm
	 * @return 通用返回对象
	 */
	@Override
	public R<String> confirmResource(List<String> resourceCodes, boolean isConfirm) {
		if (!CollectionUtils.isEmpty(resourceCodes)) {
			int status = isConfirm ? 1 : 0;
			List<ConfResource> confResourceList = super.list(new LambdaQueryWrapper<ConfResource>()
					.in(ConfResource::getResourceCode, resourceCodes));

			List<ConfResource> filterList = confResourceList.stream().filter(resource -> !Objects.equals(resource.getIsConfirm(), status))
					.collect(Collectors.toList());

			if (filterList.isEmpty()) {
				return R.ok();
			}

			List<String> confResources = confResourceList.stream().map(ConfResource::getResourceCode).collect(Collectors.toList());
			LambdaUpdateWrapper<ConfResource> confResourceLambdaUpdateWrapper = Wrappers.lambdaUpdate();
			confResourceLambdaUpdateWrapper.in(ConfResource::getResourceCode, confResources);
			confResourceLambdaUpdateWrapper.set(ConfResource::getIsConfirm, status);
			if (!super.update(confResourceLambdaUpdateWrapper)) {
				return R.failed("");
			}

			//确认/取消服务资源对应的步骤
			UpdateWrapper<ConfStep> stepUpdateWrapper = new UpdateWrapper<>();
			stepUpdateWrapper.in("step_code", confResources);
			stepUpdateWrapper.set("is_confirm", status);
			confStepService.update(stepUpdateWrapper);

			for (ConfResource confResource : filterList) {
				String parentResourceCode = confResource.getParentResourceCode();
				//判断父服务资源是否存在
				if (CharSequenceUtil.isBlank(parentResourceCode)) {
					continue;
				}
				QueryWrapper<ConfExclusiveIndicator> exclusiveIndicatorQueryWrapper = new QueryWrapper<>();
				exclusiveIndicatorQueryWrapper.in(RESOURCE_CODE, parentResourceCode);
				List<ConfExclusiveIndicator> confExclusiveIndicators = indicatorService.list(exclusiveIndicatorQueryWrapper);
				if (!CollectionUtils.isEmpty(confExclusiveIndicators)) {
					QueryWrapper<ConfExclusiveIndicator> indicatorQueryWrapper = new QueryWrapper<>();
					indicatorQueryWrapper.in(RESOURCE_CODE, confResource.getResourceCode());
					indicatorService.remove(indicatorQueryWrapper);
				}
				if (isConfirm) {
					for (ConfExclusiveIndicator exclusiveIndicator : confExclusiveIndicators) {
						exclusiveIndicator.setId(null);
						exclusiveIndicator.setResourceCode(confResource.getResourceCode());
						confResource.setCreateBy(SecurityUtils.getUser().getName());
						confResource.setCreateTime(LocalDateTime.now());
						confResource.setUpdateBy(SecurityUtils.getUser().getName());
						confResource.setUpdateTime(LocalDateTime.now());
					}
				}
				indicatorService.saveOrUpdateBatch(confExclusiveIndicators);
			}
		}
		return R.ok();
	}

	@Override
	public List<ConfResource> queryResourceCodeByStatus(Integer status) {
		return confResourceMapper.queryResourceCodeByStatus(status);
	}

	/**
	 * 根据系统id和业务编码查询业务服务资源
	 *
	 * @param systemId
	 * @param businessCode
	 * @return
	 */
	@Override
	public Set<String> getResourceBySystemIdAndBusinessCode(Integer systemId, String businessCode) {

		List<ConfStep> confSteps = confStepService.list(new LambdaQueryWrapper<ConfStep>().eq(ConfStep::getSystemId, systemId)
				.eq(ConfStep::getBusinessCode, businessCode));

		List<String> graphIds = confSteps.stream().map(step -> getGraphId(systemId, businessCode, step.getStepCode())).collect(Collectors.toList());
		List<ConfNodeProperty> confNodeProperties = confNodePropertyService.list(new LambdaQueryWrapper<ConfNodeProperty>()
				.eq(ConfNodeProperty::getType, GraphType.END_AND_END_RELATIONSHIP.getType())
				.in(ConfNodeProperty::getGraphId, graphIds));
		Set<String> resourceSet = confNodeProperties.stream()
				.map(property -> (String) JSONUtil.parseObj(property.getMeta()).get("resourceCode")).collect(Collectors.toSet());

		return resourceSet;
	}

	/**
	 *  更新业务服务资源为未使用，用网端服务资源url模糊匹配
	 * @param resourceStr
	 */
	@Override
	public void updateBusinessResourceNoUsed(String resourceStr) {
		confResourceMapper.updateBusinessResourceNoUsed(resourceStr);
	}

	/**
	 * 新增数据
	 *
	 * @param confResource 实例对象
	 * @return 通用返回对象
	 */
	@Override
	public R<String> saveConfig(ConfResource confResource) {
		if (!checkResourceDuplicates(confResource)){
			String username = SecurityUtils.getUser().getName();
			confResource.setResourceCode(StringUtils.generate16Md5(confResource.getIdentifyStr()));
			confResource.setName(confResource.getType() + "00000000");
			confResource.setCreateBy(username);
			confResource.setCreateTime(LocalDateTime.now());
			confResource.setUpdateBy(username);
			confResource.setUpdateTime(LocalDateTime.now());
			super.save(confResource);
			return R.ok();
		}
		return R.failed("识别串已存在");
	}

	/**
	 * 通过主键更新数据
	 *
	 * @param confResource 实例对象
	 * @return 通用返回对象
	 */
	@Override
	public R<String> updateDataById(ConfResource confResource) {
		if (!checkResourceDuplicates(confResource)){
			if(super.getById(confResource.getId()) == null){
				return R.failed("id不存在");
			}
			confResource.setName(confResource.getType() + "00000000");
			confResource.setUpdateBy(SecurityUtils.getUser().getName());
			confResource.setUpdateTime(LocalDateTime.now());
			if (!super.updateById(confResource)) {
				return R.failed("更新失败,请检查查询条件");
			}
			return R.ok();
		}
		return R.failed("识别串已存在");
	}

	@Override
	public int removeParentResourceExclusiveIndicators(String resourceCoding) {
		int status = 0;

		// 1、查询服务资源
		BusinessResource br = new BusinessResource();
		br.setResourceCoding(resourceCoding);
		LambdaQueryWrapper<ConfResource> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(ConfResource::getResourceCode, resourceCoding);
		List<ConfResource> businessResourceList = super.list(queryWrapper);
//		List<ConfResource> businessResourceList = confResourceMapper.queryList(br);

		// 2、判断父服务资源是否存在
		if (businessResourceList.size() > 0) {
			ConfResource businessResource = businessResourceList.get(0);
			String resourceKeyCoding = businessResource.getParentResourceCode();
			if (org.springframework.util.StringUtils.isEmpty(resourceKeyCoding)) {
				// 不存在父服务资源
				return status;
			}

			// 存在父服务资源
			// 查询父服务资源的专属指标
//			ExclusiveIndicators ei = new ExclusiveIndicators();
//			ei.setResourceCoding(resourceKeyCoding);
//			List<ExclusiveIndicators> eiList = exclusiveIndicatorsService.queryList(ei);

			LambdaQueryWrapper<ConfExclusiveIndicator> exclusiveIndicatorLambdaQueryWrapper = Wrappers.lambdaQuery();
			exclusiveIndicatorLambdaQueryWrapper.eq(ConfExclusiveIndicator::getResourceCode, resourceKeyCoding);
			List<ConfExclusiveIndicator> eiList = indicatorService.list(exclusiveIndicatorLambdaQueryWrapper);

			// 删除父服务资源同步过来的专属指标，用字段code删除，如果code相同表示是从父服务资源同步过来的专属指标
			Map<String, Object> map = new HashMap<>();
			map.put("resourceCoding", resourceCoding);
			map.put("codeList", eiList.stream().map(ConfExclusiveIndicator::getEiCode).collect(Collectors.toList()));
			indicatorService.deleteSyncExclusiveIndicators(map);
		}
		return status;
	}

	@Override
	public int updateByResourceCodes(BusinessResource businessResource) {
		if(!CollectionUtils.isEmpty(businessResource.getStringlist())){
			return confResourceMapper.updateByResourceCodes(businessResource);
		}
		return 0;
	}

	/**
	 * 同步父资源的专属指标
	 * @throws Exception
	 */
	@Override
	public int syncParentResourceExclusiveIndicators(String resourceCoding) {
		int status = 0;

		// 1、查询服务资源
		BusinessResource br = new BusinessResource();
		br.setResourceCoding(resourceCoding);
		LambdaQueryWrapper<ConfResource> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(ConfResource::getResourceCode, resourceCoding);
		List<ConfResource> businessResourceList = super.list(queryWrapper);
//		List<BusinessResource> businessResourceList = businessResourceService.queryList(br);

		// 2、判断父服务资源是否存在
		if (businessResourceList.size() > 0) {
			ConfResource businessResource = businessResourceList.get(0);
			String resourceKeyCoding = businessResource.getParentResourceCode();
			if (org.springframework.util.StringUtils.isEmpty(resourceKeyCoding)) {
				// 不存在父服务资源
				return status;
			}

			// 存在父服务资源
			// 查询父服务资源的专属指标
//			ExclusiveIndicators ei = new ExclusiveIndicators();
//			ei.setResourceCoding(resourceKeyCoding);
//			List<ExclusiveIndicators> eiList = exclusiveIndicatorsService.queryList(ei);

			LambdaQueryWrapper<ConfExclusiveIndicator> excluedQuery = Wrappers.lambdaQuery();
			excluedQuery.eq(ConfExclusiveIndicator::getResourceCode, resourceKeyCoding);
			List<ConfExclusiveIndicator> eiList = indicatorService.list(excluedQuery);

			// 同步专属指标到子服务资源
			List<String> codeList = new ArrayList<>();
			List<ConfExclusiveIndicator> syncList = new ArrayList<>();
			for (ConfExclusiveIndicator e : eiList) {
				ConfExclusiveIndicator indicators = new ConfExclusiveIndicator();
				indicators.setName(e.getName());
				indicators.setKeyword(e.getKeyword());
				indicators.setKeywordType(e.getKeywordType());
				indicators.setSource(e.getSource());
				indicators.setResourceCode(resourceCoding);
				indicators.setFormatStr(e.getFormatStr());
				indicators.setMatchRegular(e.getMatchRegular());
				// 设置同步时间
				indicators.setSynTime(LocalDateTime.now());
				// 设置专属指标编码
				codeList.add(e.getEiCode());
				indicators.setEiCode(e.getEiCode());

				RequestAttributes ra = RequestContextHolder.getRequestAttributes();

				//如果由定时器去跑任务导入，那么是获取不到当前用户登录信息
				if(ra == null) {
					// 创建人
					indicators.setCreateBy("admin");
				}else {
					// 创建人
					indicators.setCreateBy(null);
				}
				// 创建时间
				indicators.setCreateTime(LocalDateTime.now());
				syncList.add(indicators);
			}
			if (codeList.size() > 0) {
				// 存在已有父资源的专属指标，先进行删除
				Map<String, Object> map = new HashMap<>();
				map.put("resourceCoding", resourceCoding);
				map.put("codeList", codeList);
				indicatorService.deleteSyncExclusiveIndicators(map);
			}
			if (syncList.size() >0){
				indicatorService.saveBatch(syncList);
			}
		}
		return status;
	}


	/**
	 * 获取关系图id
	 * @param systemId
	 * @param businessCode
	 * @param stepCode
	 * @return
	 */
	private String getGraphId(Integer systemId, String businessCode, String stepCode) {
		return String.valueOf(HashUtil.cityHash32((systemId + businessCode +stepCode).getBytes()));
	}

	/**
	 * 判断业务名称是否重复
	 * @param confResource 业务对象
	 */
	private boolean checkResourceDuplicates(ConfResource confResource) {
		QueryWrapper<ConfResource> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("identify_str", confResource.getIdentifyStr());
		if(confResource.getId() != null){
			queryWrapper.ne("id", confResource.getId());
		}
		return !super.list(queryWrapper).isEmpty();
	}
}
